<script setup lang="tsx">
import { ref, reactive, onMounted, watch, computed } from 'vue'
import {
  getAssetListAPI,
  // getCountTopAPI,
  getSearchServiceTopAPI,
  getSearchOsTopAPI,
  getSearchDeviceTopAPI,
  getCountrtCountTopAPI,
  getSearchRecordsAPI,
  getSearchHtmlTitleAPI,
  getSearchIconAPI
} from '@/api/search/index'
import type { AxiosResponse } from 'axios'
import { HttpCodeEnum } from '@packages/share/enums'
import { useRoute } from 'vue-router'
import { useSearch } from '@/hooks/component'
import { Search } from '@element-plus/icons-vue'
import ListCard from '@/components/common/listCard.vue'
import ResultList from './components/resultList.vue'
import operateDrawer from '../components/grammar/index.vue'
import HistorySearch from './components/asstInfo/compent/historySearch.vue'
import { useSearchPage, type OptionsItem } from '@/hooks/web'
import TipsSearchInput from '../components/TipsSearchInput.vue'
import MapChart from './components/mapChart.vue'
import ListTree from '@/components/common/listTree.vue'

// 搜索引擎携带的关键词
const route = useRoute()
const infokeyword = ref(route.query.keyword)
const active:any = ref(route.query.active)
// 左侧列表默认展开项
const activeNames = ref(['1', '2', '3', '4', '5', '6'])
// 搜索语法抽屉
const operateRef = ref()
// 树形控件一级选择
const currentLeavel1 = ref()
// 树形控件
const TreeRef = ref()

const search: any = ref('')

const { table, page, getRecords, ruleForm } = useSearchPage(getAssetListAPI, infokeyword.value)
const { handleSearch } = useSearch('advancedRef', ruleForm, getRecords)

const liftClick = [
  { id: "country", children: ["province", "city"] },
  { id: "service", children: [] },
  { id: "os", children: [] },
  { id: "deviceInformation.secondaryType", children: [] },
  { id: "html.title", children: [] },
  { id: "html.favicon", children: [] },
]
// 基础数据
const Info = reactive({
  HisSearchList: [],
  CountryTopList: [],
  ServiceTopList: [],
  OsTopList: [],
  DeviceTopList: [],
  TitleTOPList: [],
  IconTOPList: []
})
const getHisrecord = () => {
  // 获取历史搜索记录
  getSearchRecordsAPI().then((res: AxiosResponse) => {
    Info.HisSearchList = res.data
  })
}
const getInfo = (initFlag?: boolean, value: any = {}) => {
  if (initFlag || !search.value.keyword.includes('country')) {
    //获取国家统计数据
    getCountrtCountTopAPI(value).then((res: AxiosResponse) => {
      const { code, rows } = res.data
      if (code === HttpCodeEnum.SUCCESS) {
        Info.CountryTopList = rows
      }
    })
    TreeRef.value.Reset()
    currentLeavel1.value = null
  }
  if (initFlag || !search.value.keyword.includes('service')) {
    //获取服务统计数据
    getSearchServiceTopAPI(value).then((res: AxiosResponse) => {
      const { code, rows } = res.data
      if (code === HttpCodeEnum.SUCCESS) {
        Info.ServiceTopList = rows
      }
    })
  }
  if (initFlag || !search.value.keyword.includes('os')) {
    //获取系统统计数据
    getSearchOsTopAPI(value).then((res: AxiosResponse) => {
      const { code, rows } = res.data
      if (code === HttpCodeEnum.SUCCESS) {
        Info.OsTopList = rows
      }
    })
  }
  if (initFlag || !search.value.keyword.includes('deviceInformation.secondaryType')) {
    //获取设备统计数据
    getSearchDeviceTopAPI(value).then((res: AxiosResponse) => {
      const { code, rows } = res.data
      if (code === HttpCodeEnum.SUCCESS) {
        Info.DeviceTopList = rows.map(item => {
          let key;
          try {
            // 尝试解析 key 是否为 JSON 对象
            const parsedKey = JSON.parse(item.key);
            key = parsedKey.name; // 如果是对象，取 name 属性
          } catch (error) {
            // 如果 key 不是 JSON 对象，则直接取值
            key = item.key;
          }
          return {
            value: item.value,
            key: key
          };
        })
      }
    })
  }
  if (initFlag || !search.value.keyword.includes('html.title')) {
    //获取网页标题
    getSearchHtmlTitleAPI(value).then((res: AxiosResponse) => {
      const { code, rows } = res.data
      if (code === HttpCodeEnum.SUCCESS) {
        Info.TitleTOPList = rows
      }
    })
  }
  //获取Icon图标
  getSearchIconAPI(value).then((res: AxiosResponse) => {
    const { code, rows } = res.data
    if (code === HttpCodeEnum.SUCCESS) {
      Info.IconTOPList = rows
    }
  })
}
//搜索
const GoSearch = () => {
  ruleForm.search = search.value.keyword
  getInfo(false, { search: search.value.keyword })
  handleSearch('searchValue')
}
// 历史搜索点击事件
const HisClick = (key: string) => {
  const regex = /(\s*&&\s*)?(\w+)\s*(:|!=)\s*("[^"]*"|\*)(\s*&&\s*(\w+)\s*(:|!=)\s*("[^"]*"|\*))*/g;
  const match = regex.exec(key); // 使用 exec 方法获取匹配结果
  if (match) {
    if (match[2] === 'country') {
      currentLeavel1.value = Info.CountryTopList.find(item => item.key === match[4].replace(/^"|"$/g, ""))
    }
    // 一级
    SearchStrUpdate(match[2], match[4].replace(/^"|"$/g, ""))
    // 二级？
    if (match[6]) {
      SearchStrUpdate(match[6], match[8].replace(/^"|"$/g, ""))
    }
    // 三级？
    if (match[10]) {
      SearchStrUpdate(match[10], match[12].replace(/^"|"$/g, ""))
    }
  }
}

// 统计列表点击事件
const Click = (title: string, key: string) => {
  SearchStrUpdate(title, key)
}
// 树形控件点击
const TreeClick = (title: any, node: any) => {
  if (node.level === 1) {
    currentLeavel1.value = node.data
    SearchStrUpdate(title, node.data.key)
  } else {
    leavel1Parent(node)
    const target = liftClick.find(item => item.id === title)
    SearchStrUpdate(title, node.parent.data.key)
    SearchStrUpdate(target.children[node.level - 2], node.data.key)
  }
}
// 循环查找初始节点
const leavel1Parent = (node: any) => {
  if (node.parent.level === 1) {
    currentLeavel1.value = node.parent.data
  } else (
    leavel1Parent(node.parent)
  )
}


// 地图:国家选择
const selectMap = (country: any) => {
  currentLeavel1.value = Info.CountryTopList.find(item => item.key === country)
  SearchStrUpdate('country', country)
}

// 树形控件筛选
const CountryShowList = () => {
  if (!currentLeavel1.value) {
    return Info.CountryTopList
  }
  return Info.CountryTopList.filter(item => item === currentLeavel1.value)
}
// 搜索词条拼接
const SearchStrUpdate = (name: string, value: string) => {
  // 搜索栏为空
  if (!search.value.keyword) {
    search.value.keyword = `${name} : "${value}"`
  }
  else {
    // 词条存在
    if (search.value.keyword.includes(name)) {
      const regex = new RegExp(`(\\s*&&\\s*)?(${name})\\s*(:|!=)\\s*("[^"]*"|\\*)`, 'g');
      search.value.keyword = search.value.keyword.replace(regex, (Str, group1, Name, group3, Value) => {
        const newValue = `"${value}"`;
        return (group1 || '') + Name + ' ' + group3 + ' ' + newValue;
      });
      // 子词条是否存在，存在则移除
      const childnames = liftClick.find(item => item.id === name)?.children
      const haschild = childnames.some(item => search.value.keyword.includes(item))
      if (haschild) {
        const findregex = new RegExp(childnames.join("|"), "g");
        const matches = search.value.keyword.match(findregex);
        matches.forEach(item => {
          const regex = new RegExp(`(\\s*&&\\s*)?(${item})\\s*(:|!=)\\s*("[^"]*"|\\*)`, 'g');
          search.value.keyword = search.value.keyword.replace(regex, (match) => {
            return '';
          });
        });
      }
    }
    // 词条不存在
    else {
      search.value.keyword += ` && ${name} : "${value}"`
    }
  }
  // 相关搜索列表
  GoSearch()
}
onMounted(() => {
  // 传入携带的搜索词
  search.value.keyword = infokeyword.value || ''
  getHisrecord()
  getInfo(true, { search: infokeyword.value })
})
</script>

<template>
  <div class="jm-mainbox">
    <!-- 搜索 -->
    <div class="searchbox jm-bg-color">
      <div class="search">
        <TipsSearchInput ref="search" class="input-search" :active="active" @keyup.enter="GoSearch" />
        <jm-button type="primary" :icon="Search" @click="GoSearch">搜索</jm-button>
        <jm-button type="primary" :icon="Search" @click="operateRef.show()">搜索语法</jm-button>
      </div>
      <div class="relativeearch">
        <!-- 历史搜索 -->
        <HistorySearch :tags="Info.HisSearchList" class="search flex" @concatValue="HisClick" />
      </div>
    </div>

    <!-- 搜索结果 -->
    <div class="mainbox">
      <!-- 搜索结果左 -->
      <div class="search-left jm-bg-color">
        <jm-collapse v-model="activeNames">
          <jm-collapse-item name="1">
            <template #title>
              <div class="header">国家统计Top5</div>
            </template>
            <ListTree ref="TreeRef" :list="CountryShowList()" @concatValue="TreeClick" :title="liftClick[0].id" />
            <MapChart class="chart-content" @addCountry="selectMap" :MapList="Info.CountryTopList" />
          </jm-collapse-item>
          <jm-collapse-item name="2">
            <template #title>
              <div class="header">服务统计Top5</div>
            </template>
            <ListCard :list="Info.ServiceTopList" @concatValue="Click" :title="liftClick[1].id" />
          </jm-collapse-item>
          <jm-collapse-item name="3">
            <template #title>
              <div class="header">系统统计Top5</div>
            </template>
            <ListCard :list="Info.OsTopList" @concatValue="Click" :title="liftClick[2].id" />
          </jm-collapse-item>
          <jm-collapse-item name="4">
            <template #title>
              <div class="header">设备统计Top5</div>
            </template>
            <ListCard :list="Info.DeviceTopList" @concatValue="Click" :title="liftClick[3].id" />
          </jm-collapse-item>
          <jm-collapse-item name="5">
            <template #title>
              <div class="header">网页标题排名</div>
            </template>
            <ListCard :list="Info.TitleTOPList" @concatValue="Click" :title="liftClick[4].id" />
          </jm-collapse-item>
          <jm-collapse-item name="6">
            <template #title>
              <div class="header">网站Icon图标</div>
            </template>
            <ListCard :list="Info.IconTOPList" @concatValue="Click" :title="liftClick[5].id" />
          </jm-collapse-item>
        </jm-collapse>
      </div>
      <!-- 搜索结果右 -->
      <div class="search-right">
        <div class="result flex jm-bg-color">获取{{ page.total }}条匹配结果</div>
        <ResultList class="jm-bg-color" v-for="item in table.records" :key="item.id" :info="item" />
        <div class="jm-bg-color">
          <jmp-pagination v-model:page="page.pageNum" v-model:limit="page.pageSize" v-model:total="page.total" />
        </div>
      </div>
    </div>
    <operateDrawer ref="operateRef" />
  </div>
</template>

<style scoped lang="scss">
.flex {
  display: flex;
  flex-wrap: wrap;
}

.searchbox {
  height: auto;

  .search {
    display: flex;
    padding: 0 0.625rem 0.625rem 0.625rem;

    .input-search {
      flex: 1
    }
  }
}

.mainbox {
  width: 100%;
  display: flex;
  margin-top: 0.625rem;
  justify-content: space-between;

  .search-left {
    width: 18.75rem;
    padding: 0.625rem;

    .header {
      color: #444;
      font-weight: 700;
      font-size: 1.25rem;
    }

    .chart-content {
      width: 100%;
      height: 12.5rem;
    }
  }

  .search-right {
    flex: 1;
    margin-left: 0.625rem;

    .result {
      padding: 0.625rem 1.25rem;
      align-items: center;
      height: 3.75rem;
      color: var(--el-color-primary);
      margin-bottom: 0.625rem;
    }
  }
}
</style>
